package primetest.impl.dao;

import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import primetest.dto.MedicineDto;
import primetest.impl.dao.MedicineDao;
import primetest.impl.dao.Transaction;

public class MedicineDao implements Serializable {

	/**
	 *
	 */
	private static final long serialVersionUID = 6551770662358620809L;

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private static List<MedicineDto> allItems = null;
	private static HashMap<String, MedicineDto> map = null;

	@Inject
	public MedicineDao() {
	}

	public List<MedicineDto> getAllList(Transaction transaction) throws IOException {
		if (allItems != null) {
			return allItems;
		}
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		map = new HashMap<String, MedicineDto>();
		try {

			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(GET_ALL);
			resultSet = prepareStatement.executeQuery();

			while (resultSet.next()) {
				MedicineDto medicineDto = makeMedicineDto(transaction, resultSet);
				map.put(medicineDto.getKey(), medicineDto);
			}
			allItems = new ArrayList<MedicineDto>(map.values());
			return allItems;
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}
	}

	private MedicineDto makeMedicineDto(Transaction transaction,
			ResultSet resultSet) throws SQLException, IOException {
		MedicineDto medicineDto = new MedicineDto();
		medicineDto.setKey(resultSet.getString(1));
		medicineDto.setName(resultSet.getString(2));
		medicineDto.setGenericNumber(resultSet.getString(3));
		medicineDto.setNote(resultSet.getString(4));
		medicineDto.setPrice(resultSet.getFloat(5));
		medicineDto.setQuantity(resultSet.getInt(6));
		medicineDto.setOrderedQuantity(resultSet.getInt(7));
		medicineDto.setSoldQuantity(resultSet.getInt(8));
		return medicineDto;
	}

	public void addMedicine(Transaction transaction, MedicineDto medicineDto)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(INSERT_ONE);
			prepareStatement.setString(1, medicineDto.getKey());
			prepareStatement.setString(2, medicineDto.getName());
			prepareStatement.setString(3, medicineDto.getGenericNumber());
			prepareStatement.setString(4, medicineDto.getNote());
			prepareStatement.setFloat(5, medicineDto.getPrice());
			prepareStatement.setInt(6, medicineDto.getQuantity());
			prepareStatement.setInt(7, medicineDto.getOrderedQuantity());
			prepareStatement.setInt(8, medicineDto.getSoldQuantity());
			prepareStatement.executeUpdate();
			map.put(medicineDto.getKey(), medicineDto);
			allItems.add(medicineDto);
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}
	}

	public void modifyQuantity(Transaction transaction, MedicineDto m, int q) throws IOException {
		m.setQuantity(m.getQuantity() + q);
		updateMedicine(transaction, m);
	}

	public MedicineDto findMedicine(Transaction transaction, String key) throws IOException {
		if (map == null) {
			getAllList(transaction);
		}
		return map.get(key);
	}

	public void updateMedicine(Transaction transaction, MedicineDto medicineDto)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
//		allItems = null;

		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(UPDATE_ONE);
			prepareStatement.setString(8, medicineDto.getKey());
			prepareStatement.setString(1, medicineDto.getName());
			prepareStatement.setString(2, medicineDto.getGenericNumber());
			prepareStatement.setString(3, medicineDto.getNote());
			prepareStatement.setFloat(4, medicineDto.getPrice());
			prepareStatement.setInt(5, medicineDto.getQuantity());
			prepareStatement.setInt(6, medicineDto.getOrderedQuantity());
			prepareStatement.setInt(7, medicineDto.getSoldQuantity());
			prepareStatement.executeUpdate();
//			map.put(medicineDto.getKey(), medicineDto);
//			allItems = new ArrayList<MedicineDto>(map.values());
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}

	}

	public void deleteMedicine(Transaction transaction, String medicineSeq)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;

		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(DELETE_ONE);
			prepareStatement.setString(1, medicineSeq);
			prepareStatement.executeUpdate();
			allItems.remove(map.remove(medicineSeq));
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}

	}

	private static final String GET_ALL = "select key_1, name, gen_number, note, price, quantity, ordered_quantity, soldQuantity from s_medicine order by name";
	private static final String INSERT_ONE = "insert into s_medicine(key_1, name, gen_number, note, price, quantity, ordered_quantity, soldQuantity) values (?, ?, ?, ?, ?, ?, ?, ?)";
	private static final String UPDATE_ONE = "update s_medicine set name = ?, gen_number = ?, note = ?, price = ?, quantity = ?, ordered_quantity = ?, soldQuantity = ? where key_1 = ?";
	private static final String DELETE_ONE = "delete from s_medicine where key_1 = ?";
}
